home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / smaltalk / manchest.lha / MANCHESTER / manchester / 2.2 / Bouncer.st < prev    next >
Text File  |  1993-07-24  |  23KB  |  846 lines

  1. "    NAME        Bouncer
  2.     AUTHOR        TPH@cs.man.ac.uk
  3.     FUNCTION bounces your shapes around the screen 
  4.     ST-VERSIONS    2.2
  5.     PREREQUISITES     
  6.     CONFLICTS    
  7.     DISTRIBUTION      world
  8.     VERSION        1.1
  9.     DATE    22 Jan 1989
  10. SUMMARY    Bouncer
  11.     provides a hierarchy of classes of things which can
  12.    `bounce' around the screen.  These include lines, rectangles and
  13.    boxes, curves and circles, and parallelograms (yes, really!).  This
  14.    is an improved version of the goodie originally provided (by TPH)
  15.    under this name.  Concrete subclasses are able to display
  16.    themselves directly onto the screen, or may be used together with
  17.    BouncerView and BouncerController.  Only known to work with VI2.2
  18.    images; could probably be made to work with earlier images by
  19.    replacing class Model with class Object.(2.2). TPH
  20. "!
  21. Model subclass: #Bouncer
  22.     instanceVariableNames: 'positions firstStep secondStep boundingBox numberOfLines '
  23.     classVariableNames: 'DefaultFirstStep DefaultNumberOfLines DefaultSecondStep NumberOfLines '
  24.     poolDictionaries: ''
  25.     category: 'Graphics-Bouncer'!
  26. Bouncer comment:
  27. 'I represent an abstract superclass of things which are able to
  28. bounce around in a closed (2D) space, and can be represented
  29. by two points.  I can display directly onto the Display, or I can
  30. be used in conjuction with BouncerView and BouncerController.
  31. My instance variables are:
  32.  
  33. positions        An OrderedCollection of Array, each containing two Points.
  34.                 Points are removed from one end of this OrderedCollection
  35.                 and generated anew at the other.
  36.  
  37. firstStep        These two instance variables are Points representing
  38. secondStep        delta changes for new endPoint generation.
  39.  
  40. boundingBox    A Rectangle indicating the region within which things can
  41.                 be displayed.
  42.  
  43. numberOfLines    The number of Arrays in <positions>.  This can be changed
  44.                 on the fly, if desired.
  45.  
  46. I have a number of default values (as Class variables) which may be used
  47. by my concrete subclasses.
  48. '!
  49.  
  50.  
  51. !Bouncer methodsFor: 'initialize-release'!
  52.  
  53. initialize
  54.     "Initialize instance variables.  Set up the initiali positions for each
  55.      element."
  56.  
  57.     boundingBox _ Display boundingBox    .
  58.     self initializeLinesAndSteps.
  59.     self setStartLocations.! !
  60.  
  61. !Bouncer methodsFor: 'accessing'!
  62.  
  63. boundingBox
  64.     "Answer with the rectangle in which the lines are displayed."
  65.  
  66.     ^boundingBox!
  67.  
  68. boundingBox: aRectangle
  69.     "Set the rectangle in which the lines are displayed to aRectangle."
  70.  
  71.     boundingBox _ aRectangle!
  72.  
  73. firstStep
  74.     "Answer with the first step value."
  75.  
  76.     ^firstStep!
  77.  
  78. firstStep: aPoint
  79.     "Set the first step value to aPoint."
  80.  
  81.     firstStep _ aPoint.!
  82.  
  83. numberOfLines
  84.     "Answer with the number of lines."
  85.  
  86.     ^numberOfLines!
  87.  
  88. numberOfLines: aNumber
  89.     "Set the number of lines to be aNumber."
  90.  
  91.     numberOfLines _ aNumber!
  92.  
  93. positions
  94.     "Answer with the orderedCollection of end-points."
  95.  
  96.     ^positions!
  97.  
  98. secondStep
  99.     "Answer with the second step value."
  100.  
  101.     ^secondStep!
  102.  
  103. secondStep: aPoint
  104.     "Set the second step value to aPoint."
  105.  
  106.     secondStep _ aPoint.! !
  107.  
  108. !Bouncer methodsFor: 'moving'!
  109.  
  110. move
  111.     "Update the positions of the receiver."
  112.  
  113.     | length |
  114.     length _ positions size.
  115.     length > numberOfLines ifTrue: [self display: positions removeLast].
  116.     length >= numberOfLines ifTrue: [self display: positions removeLast].
  117.     self display:
  118.         (positions addFirst:
  119.             (Array with: self newStart with: self newEnd))! !
  120.  
  121. !Bouncer methodsFor: 'displaying'!
  122.  
  123. display: anArray
  124.     "Display the receiver in a manner represented by the two points in anArray"
  125.  
  126.     self subclassResponsibility! !
  127.  
  128. !Bouncer methodsFor: 'private'!
  129.  
  130. initializeLinesAndSteps
  131.     "Set the the default number of lines, and the default step values."
  132.  
  133.     numberOfLines _ DefaultNumberOfLines.
  134.     firstStep _ DefaultFirstStep copy.
  135.     secondStep _ DefaultSecondStep copy!
  136.  
  137. newEnd
  138.     "Answer with the new value of the end point, updating
  139.      the step value if a bounce has occured."
  140.  
  141.     | end |
  142.     end _ (positions first at: 2) + secondStep.
  143.     (end x >= boundingBox corner x or:
  144.         [end x <= boundingBox origin x]) ifTrue: [
  145.             secondStep x: secondStep x negated.
  146.             end x: end x + (2 * secondStep x)].
  147.     (end y >= boundingBox corner y or:
  148.         [end y <= boundingBox origin y]) ifTrue: [
  149.             secondStep y: secondStep y negated.
  150.             end y: end y + (2 * secondStep y)].
  151.     ^end!
  152.  
  153. newStart
  154.     "Answer with the new value of the start point, updating
  155.      the step value if a bounce has occured."
  156.  
  157.     | start |
  158.     start _ (positions first at: 1) + firstStep.
  159.     (start x >= boundingBox corner x or:
  160.         [start x <= boundingBox origin x]) ifTrue: [
  161.             firstStep x: firstStep x negated.
  162.             start x: start x + (2 * firstStep x)].
  163.     (start y >= boundingBox corner y or:
  164.         [start y <= boundingBox origin y]) ifTrue: [
  165.             firstStep y: firstStep y negated.
  166.             start y: start y + (2 * firstStep y)].
  167.     ^start!
  168.  
  169. setStartLocations
  170.     "Set the start locations to be in the centre of the bounding box."
  171.  
  172.     self startAt: boundingBox center and: boundingBox center + (4@0)!
  173.  
  174. startAt: firstPoint and: secondPoint
  175.     "The receiver is initially drawn between firstPoint and secondPoint."
  176.  
  177.     positions _ OrderedCollection new.
  178.     numberOfLines timesRepeat: [
  179.         positions addLast: (Array with: firstPoint with: secondPoint)].! !
  180. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  181.  
  182. Bouncer class
  183.     instanceVariableNames: ''!
  184.  
  185.  
  186. !Bouncer class methodsFor: 'instance creation'!
  187.  
  188. new
  189.     "Answer with an initialized instance of the receiver."
  190.  
  191.     ^super new initialize! !
  192.  
  193. !Bouncer class methodsFor: 'class initialization'!
  194.  
  195. initialize
  196.     "Initialize class variables."
  197.     "Bouncer initialize."
  198.  
  199.     DefaultNumberOfLines _ 50.
  200.     DefaultFirstStep _ 3@4.
  201.     DefaultSecondStep _ 5@2! !
  202.  
  203. !Bouncer class methodsFor: 'examples'!
  204.  
  205. example1
  206.     "BouncerRectangle example1"
  207.     "BouncerLine example1."
  208.     "BouncerBox example1."
  209.     "BouncerParallelogram example1."
  210.     "BouncerCurve example1."
  211.     "BouncerCircle example1."
  212.  
  213.     | bouncer |
  214.     Display white.
  215.     bouncer _ self new.
  216.     [Sensor redButtonPressed not] whileTrue: [bouncer move].
  217.     ScheduledControllers restore!
  218.  
  219. example2
  220.     "BouncerLine example2"
  221.     "BouncerRectangle example2."
  222.     "BouncerBox example2."
  223.     "BouncerParallelogram example2."
  224.     "BouncerCurve example2."
  225.     "BouncerCircle example2."
  226.  
  227.     | bouncer box |
  228.     box _ Rectangle origin: 50@50 extent: 400@300.
  229.     Display white: box.
  230.     bouncer _ self new boundingBox: box.
  231.     bouncer setStartLocations.
  232.     [Sensor redButtonPressed not] whileTrue: [bouncer move].
  233.     ScheduledControllers restore! !
  234.  
  235. Bouncer initialize!
  236.  
  237.  
  238. Bouncer subclass: #BouncerCurve
  239.     instanceVariableNames: 'curve '
  240.     classVariableNames: 'CurveDefaultFirstStep CurveDefaultNumberOfLines CurveDefaultSecondStep '
  241.     poolDictionaries: ''
  242.     category: 'Graphics-Bouncer'!
  243. BouncerCurve comment:
  244. 'I am a concrete Bouncer subclass which represents each element as
  245. a closed curve constructed from four Curves (conic sections).  The
  246. closed curve so formed just fits into a rectangle with origin and
  247. corner given by the two points representing each element.
  248. '!
  249.  
  250.  
  251. !BouncerCurve methodsFor: 'initialize-release'!
  252.  
  253. initialize
  254.     "Initialize additional instance variables."
  255.  
  256.     | form |
  257.     super initialize.
  258.     form _ Form new extent: 1@1.
  259.     form black.
  260.     curve _ Curve new form: form.! !
  261.  
  262. !BouncerCurve methodsFor: 'displaying'!
  263.  
  264. display: anArray
  265.     "Display the receiver as a closed curve represented by the
  266.      two points in anArray"
  267.  
  268.     self displayCurve: anArray!
  269.  
  270. displayBottomLeft: rect 
  271.     "Display the bottom left part of a closed curve in the rectangle rect."
  272.  
  273.     curve firstPoint: rect bottomCenter.
  274.     curve secondPoint: rect bottomLeft.
  275.     curve thirdPoint: rect leftCenter.
  276.     curve
  277.         displayOn: Display
  278.         at: 0 @ 0
  279.         clippingBox: self boundingBox
  280.         rule: Form reverse
  281.         mask: Form black!
  282.  
  283. displayBottomRight: rect
  284.     "Display the bottom right part of a curve in the rectangle rect."
  285.  
  286.     curve firstPoint: rect bottomCenter.
  287.     curve secondPoint: rect bottomRight.
  288.     curve thirdPoint: rect rightCenter.
  289.     curve
  290.         displayOn: Display
  291.         at: 0 @ 0
  292.         clippingBox: self boundingBox
  293.         rule: Form reverse
  294.         mask: Form black!
  295.  
  296. displayCurve: anArray
  297.     "Display a closed curve represented by two points."
  298.  
  299.     | rect |
  300.     rect _ Rectangle origin: (anArray at: 1) corner: (anArray at: 2).
  301.     self displayTopRight: rect.
  302.     self displayBottomRight: rect.
  303.     self displayBottomLeft: rect.
  304.     self displayTopLeft: rect!
  305.  
  306. displayTopLeft: rect
  307.     "Display the top left part of a curve in the rectangle rect."
  308.  
  309.     curve firstPoint: rect topCenter.
  310.     curve secondPoint: rect topLeft.
  311.     curve thirdPoint: rect leftCenter.
  312.     curve
  313.         displayOn: Display
  314.         at: 0 @ 0
  315.         clippingBox: self boundingBox
  316.         rule: Form reverse
  317.         mask: Form black!
  318.  
  319. displayTopRight: rect
  320.     "Display the top right part of a curve in the rectangle rect."
  321.  
  322.     curve firstPoint: rect topCenter.
  323.     curve secondPoint: rect topRight.
  324.     curve thirdPoint: rect rightCenter.
  325.     curve
  326.         displayOn: Display
  327.         at: 0 @ 0
  328.         clippingBox: self boundingBox
  329.         rule: Form reverse
  330.         mask: Form black! !
  331.  
  332. !BouncerCurve methodsFor: 'private'!
  333.  
  334. initializeLinesAndSteps
  335.     "Set the the default number of lines, and the default step
  336.      values.  Different defaults are required for closed curves."
  337.  
  338.     numberOfLines _ CurveDefaultNumberOfLines.
  339.     firstStep _ CurveDefaultFirstStep copy.
  340.     secondStep _ CurveDefaultSecondStep copy! !
  341. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  342.  
  343. BouncerCurve class
  344.     instanceVariableNames: ''!
  345.  
  346.  
  347. !BouncerCurve class methodsFor: 'class initialization'!
  348.  
  349. initialize
  350.     "Different defaults are required for curves."
  351.     "BouncerCurve initialize."
  352.  
  353.     CurveDefaultNumberOfLines _ 15.
  354.     CurveDefaultFirstStep _ -7@-6.
  355.     CurveDefaultSecondStep _ 5@8.! !
  356.  
  357. BouncerCurve initialize!
  358.  
  359.  
  360. Bouncer subclass: #BouncerRectangle
  361.     instanceVariableNames: ''
  362.     classVariableNames: 'RectangleDefaultFirstStep RectangleDefaultNumberOfLines RectangleDefaultSecondStep '
  363.     poolDictionaries: ''
  364.     category: 'Graphics-Bouncer'!
  365. BouncerRectangle comment:
  366. 'I am a concrete Bouncer class, which displays each element as a
  367. rectangle, with origin and corner given by the two points representing
  368. each element.  I simply reverse the screen color within my rectangle.'!
  369.  
  370.  
  371. !BouncerRectangle methodsFor: 'displaying'!
  372.  
  373. display: anArray
  374.     "Display the receiver as a rectangle represented by the
  375.      two points in anArray"
  376.  
  377.     self displayRectangle: anArray!
  378.  
  379. displayRectangle: anArray
  380.     "Display a rectangle given by the two points in anArray"
  381.  
  382.     Display reverse:
  383.             (Rectangle
  384.                 origin: ((anArray at: 1) min: (anArray at: 2))
  385.                 corner: ((anArray at: 1) max: (anArray at: 2)))! !
  386.  
  387. !BouncerRectangle methodsFor: 'private'!
  388.  
  389. initializeLinesAndSteps
  390.     "Set the the default number of lines, and the default step
  391.      values.  Different defaults are required for rectangles."
  392.  
  393.     numberOfLines _ RectangleDefaultNumberOfLines.
  394.     firstStep _ RectangleDefaultFirstStep copy.
  395.     secondStep _ RectangleDefaultSecondStep copy! !
  396. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  397.  
  398. BouncerRectangle class
  399.     instanceVariableNames: ''!
  400.  
  401.  
  402. !BouncerRectangle class methodsFor: 'class initialization'!
  403.  
  404. initialize
  405.     "Different defaults are required for rectangles."
  406.     "BouncerRectangle initialize."
  407.  
  408.     RectangleDefaultNumberOfLines _ 200.
  409.     RectangleDefaultFirstStep _ -2@-2.
  410.     RectangleDefaultSecondStep _ 2@2.! !
  411.  
  412. BouncerRectangle initialize!
  413.  
  414.  
  415. Bouncer subclass: #BouncerCircle
  416.     instanceVariableNames: 'circle '
  417.     classVariableNames: 'CircleDefaultFirstStep CircleDefaultNumberOfLines CircleDefaultSecondStep '
  418.     poolDictionaries: ''
  419.     category: 'Graphics-Bouncer'!
  420. BouncerCircle comment:
  421. 'I am a concrete Bouncer subclass which represents each element as
  422. a circle which just fits into a rectangle with origin and corner given
  423. by the two points representing each element.
  424. '!
  425.  
  426.  
  427. !BouncerCircle methodsFor: 'initialize-release'!
  428.  
  429. initialize
  430.     "Initialize additional instance variables."
  431.  
  432.     | form |
  433.     super initialize.
  434.     form _ Form new extent: 1@1.
  435.     form black.
  436.     circle _ Circle new form: form.! !
  437.  
  438. !BouncerCircle methodsFor: 'displaying'!
  439.  
  440. display: anArray
  441.     "Display the receiver as a circle represented by the
  442.      two points in anArray"
  443.  
  444.     self displayCircle: anArray!
  445.  
  446. displayCircle: anArray
  447.     "Display a circle in the centre of a rectangle represented by
  448.      the two points in anArray"
  449.  
  450.     | rect |
  451.     rect _ Rectangle origin: (anArray at: 1) corner: (anArray at: 2).
  452.     circle center: rect center.
  453.     circle radius: ((rect width abs min: rect height abs) // 2 max: 18).
  454.     circle
  455.         displayOn: Display
  456.         at: 0 @ 0
  457.         clippingBox: self boundingBox
  458.         rule: Form reverse
  459.         mask: Form black! !
  460.  
  461. !BouncerCircle methodsFor: 'private'!
  462.  
  463. initializeLinesAndSteps
  464.     "Set the the default number of lines, and the default step
  465.      values.  Different defaults are required for circles."
  466.  
  467.     numberOfLines _ CircleDefaultNumberOfLines.
  468.     firstStep _ CircleDefaultFirstStep copy.
  469.     secondStep _ CircleDefaultSecondStep copy! !
  470. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  471.  
  472. BouncerCircle class
  473.     instanceVariableNames: ''!
  474.  
  475.  
  476. !BouncerCircle class methodsFor: 'class initialization'!
  477.  
  478. initialize
  479.     "Different defaults are required for circles."
  480.     "BouncerCircle initialize."
  481.  
  482.     CircleDefaultNumberOfLines _ 20.
  483.     CircleDefaultFirstStep _ -7@-3.
  484.     CircleDefaultSecondStep _ 5@4.! !
  485.  
  486. BouncerCircle initialize!
  487.  
  488.  
  489. Bouncer subclass: #BouncerLineTypes
  490.     instanceVariableNames: 'pen '
  491.     classVariableNames: ''
  492.     poolDictionaries: ''
  493.     category: 'Graphics-Bouncer'!
  494. BouncerLineTypes comment:
  495. 'I am an abstract superclass representing bouncers which display
  496. themselves using lines.  I add an instance variable, pen, which is
  497. used to draw the lines (for efficiency reasons, the same pen is used
  498. throughout.)
  499.  
  500. '!
  501.  
  502.  
  503. !BouncerLineTypes methodsFor: 'initialize-release'!
  504.  
  505. initialize
  506.     "Initialize instance variables."
  507.  
  508.     super initialize.
  509.     pen _ Pen new.
  510.     pen combinationRule: Form reverse.
  511.     pen destForm: Display.
  512.     pen frame: Display boundingBox! !
  513.  
  514. !BouncerLineTypes methodsFor: 'accessing'!
  515.  
  516. boundingBox: aRectangle
  517.     "Override this message to permit the frame of the pen to be changed."
  518.  
  519.     super boundingBox: aRectangle.
  520.     pen frame: aRectangle! !
  521.  
  522. !BouncerLineTypes methodsFor: 'displaying'!
  523.  
  524. display: anArray
  525.     "Display the receiver as a line represented by the two points in anArray"
  526.  
  527.     self displayLine: anArray! !
  528.  
  529. View subclass: #BouncerView
  530.     instanceVariableNames: ''
  531.     classVariableNames: ''
  532.     poolDictionaries: ''
  533.     category: 'Graphics-Bouncer'!
  534. BouncerView comment:
  535. 'I am a view capable of displaying any concrete Bouncer subclass.
  536. I should be used together with instances of BouncerController.'!
  537.  
  538.  
  539. !BouncerView methodsFor: 'displaying'!
  540.  
  541. displayView
  542.     "Re-display the entire contents of the model."
  543.  
  544.     model boundingBox = self insetDisplayBox ifFalse: [
  545.         self controller updateBoundingBox].
  546.     model positions reverseDo: [:eachPair |
  547.         model display: eachPair].! !
  548.  
  549. !BouncerView methodsFor: 'controller access'!
  550.  
  551. defaultControllerClass
  552.     ^BouncerController! !
  553. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  554.  
  555. BouncerView class
  556.     instanceVariableNames: ''!
  557.  
  558.  
  559. !BouncerView class methodsFor: 'instance creation'!
  560.  
  561. openOn: aBouncer
  562.     "Open a new view on a Bouncer."
  563.  
  564.     "BouncerView openOn: BouncerLine new."
  565.     "BouncerView openOn: BouncerRectangle new."
  566.     "BouncerView openOn: BouncerBox new."
  567.     "BouncerView openOn: BouncerParallelogram new."
  568.     "BouncerView openOn: BouncerCircle new."
  569.     "BouncerView openOn: BouncerCurve new."
  570.  
  571.     | topView bouncerView |
  572.     topView _ StandardSystemView
  573.                     model: nil
  574.                     label: aBouncer class printString,' Demo'
  575.                     minimumSize: 221@200.
  576.     bouncerView _ self new borderWidth: 1.
  577.     bouncerView model: aBouncer.
  578.     bouncerView insideColor: Form white.
  579.     topView addSubView: bouncerView.
  580.     topView controller open! !
  581.  
  582. BouncerLineTypes subclass: #BouncerBox
  583.     instanceVariableNames: ''
  584.     classVariableNames: ''
  585.     poolDictionaries: ''
  586.     category: 'Graphics-Bouncer'!
  587. BouncerBox comment:
  588. 'I am a concrete Bouncer subclass which displays myself by drawing
  589. a 1-pixel wide box at the edge of a rectangle formed by the two
  590. points representing each element.'!
  591.  
  592.  
  593. !BouncerBox methodsFor: 'displaying'!
  594.  
  595. displayLine: anArray
  596.     "Display a box given the two points contains in anArray."
  597.  
  598.     pen place: (anArray at: 1).
  599.     pen goto: (anArray at: 1) x @ (anArray at: 2) y.
  600.     pen goto: (anArray at: 2).
  601.     pen goto: (anArray at: 2) x @ (anArray at: 1) y.
  602.     pen goto: (anArray at: 1)! !
  603.  
  604. BouncerLineTypes subclass: #BouncerParallelogram
  605.     instanceVariableNames: 'ratio oneMinusRatio '
  606.     classVariableNames: 'ParallelogramDefaultFirstStep ParallelogramDefaultNumberOfLines ParallelogramDefaultSecondStep ParallelogramFormFactor '
  607.     poolDictionaries: ''
  608.     category: 'Graphics-Bouncer'!
  609. BouncerParallelogram comment:
  610. 'I am a concrete Bouncer subclass which displays a parallelogram
  611. with major axis given by the two points representing each element.
  612. The ratio of the major to the minor axis is given by an instance
  613. variable, ratio.  For efficiency reasons, a second instance variable,
  614. oneMinusRatio, is used to avoid re-computing this value unnecessarily.'!
  615.  
  616.  
  617. !BouncerParallelogram methodsFor: 'initialize-release'!
  618.  
  619. initialize
  620.     "Initialize the form factor ratio."
  621.  
  622.     super initialize.
  623.     ratio _ ParallelogramFormFactor.
  624.     oneMinusRatio _ (1 - ParallelogramFormFactor)! !
  625.  
  626. !BouncerParallelogram methodsFor: 'displaying'!
  627.  
  628. displayLine: anArray 
  629.     "Display a parallelogram defined by the two points in anArray."
  630.  
  631.     | first second third fourth |
  632.     first _ anArray at: 1.
  633.     third _ anArray at: 2.
  634.     second _ first +
  635.         ((third x - first x * (1 - ratio)) @ (third y - first y * ratio)) rounded.
  636.     fourth _ first +
  637.         ((third x - first x * ratio) @ (third y - first y * (1 - ratio))) rounded.
  638.     pen place: first.
  639.     pen goto: second.
  640.     pen goto: third.
  641.     pen goto: fourth.
  642.     pen goto: first! !
  643.  
  644. !BouncerParallelogram methodsFor: 'private'!
  645.  
  646. initializeLinesAndSteps
  647.     "Set the the default number of lines, and the default step
  648.      values.  Different defaults are required for parallelograms."
  649.  
  650.     numberOfLines _ ParallelogramDefaultNumberOfLines.
  651.     firstStep _ ParallelogramDefaultFirstStep copy.
  652.     secondStep _ ParallelogramDefaultSecondStep copy! !
  653. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  654.  
  655. BouncerParallelogram class
  656.     instanceVariableNames: ''!
  657.  
  658.  
  659. !BouncerParallelogram class methodsFor: 'class initialization'!
  660.  
  661. initialize
  662.     "Different defaults are required for Parallelograms."
  663.     "BouncerParallelogram initialize."
  664.  
  665.     ParallelogramDefaultNumberOfLines _ 35.
  666.     ParallelogramDefaultFirstStep _ 7@9.
  667.     ParallelogramDefaultSecondStep _ 5@8.
  668.         "Should be between 0 and 1."
  669.     ParallelogramFormFactor _ (2 / 7) asFloat    "for efficiency."! !
  670.  
  671. BouncerParallelogram initialize!
  672.  
  673.  
  674. BouncerLineTypes subclass: #BouncerLine
  675.     instanceVariableNames: ''
  676.     classVariableNames: ''
  677.     poolDictionaries: ''
  678.     category: 'Graphics-Bouncer'!
  679. BouncerLine comment:
  680. 'I am a concrete bouncer class.  I display myself as a simple straight
  681. line between the two points representing each element.'!
  682.  
  683.  
  684. !BouncerLine methodsFor: 'displaying'!
  685.  
  686. displayLine: anArray
  687.     "Display a line between the two points contains in anArray."
  688.  
  689.     pen place: (anArray at: 1).
  690.     pen goto: (anArray at: 2).! !
  691.  
  692. MouseMenuController subclass: #BouncerController
  693.     instanceVariableNames: ''
  694.     classVariableNames: 'BouncerYellowButtonMenu BouncerYellowButtonMessages '
  695.     poolDictionaries: ''
  696.     category: 'Graphics-Bouncer'!
  697. BouncerController comment:
  698. 'I am a controller suitable for use with BouncerView instances, and
  699. any concrete subclass of Bouncer.  I allow the user to modify
  700. various parameters associated with Bouncers.'!
  701.  
  702.  
  703. !BouncerController methodsFor: 'initialize-release'!
  704.  
  705. initialize
  706.     "Initialize the yellow button menu."
  707.  
  708.     super initialize.
  709.     self
  710.         yellowButtonMenu: BouncerYellowButtonMenu
  711.         yellowButtonMessages: BouncerYellowButtonMessages! !
  712.  
  713. !BouncerController methodsFor: 'menu messages'!
  714.  
  715. changeNumberOfLines
  716.     "Prompt the user for a new number of lines to be displayed."
  717.  
  718.     | anAnswer |
  719.     anAnswer _ FillInTheBlank request: 'Number of lines to be displayed?'
  720.         initialAnswer: self model numberOfLines printString.
  721.     anAnswer isEmpty ifFalse: [
  722.         self model numberOfLines:
  723.             ((Number readFrom: (ReadStream on: anAnswer)) max: 2)].!
  724.  
  725. changeSteps
  726.     "Prompt the user for new values for each step size."
  727.  
  728.     | firstX firstY secondX secondY |
  729.     firstX _ FillInTheBlank request: 'First X step value?'
  730.         initialAnswer: self model firstStep x printString.
  731.     firstX isEmpty ifFalse: [
  732.         self model firstStep x:
  733.             ((Number readFrom: (ReadStream on: firstX)))].
  734.     firstY _ FillInTheBlank request: 'First Y step value?'
  735.         initialAnswer: self model firstStep y printString.
  736.     firstY isEmpty ifFalse: [
  737.         self model firstStep y:
  738.             ((Number readFrom: (ReadStream on: firstY)))].
  739.     secondX _ FillInTheBlank request: 'Second X step value?'
  740.         initialAnswer: self model secondStep x printString.
  741.     secondX isEmpty ifFalse: [
  742.         self model secondStep x:
  743.             ((Number readFrom: (ReadStream on: secondX)))].
  744.     secondY _ FillInTheBlank request: 'Second Y step value?'
  745.         initialAnswer: self model secondStep y printString.
  746.     secondY isEmpty ifFalse: [
  747.         self model secondStep y:
  748.             ((Number readFrom: (ReadStream on: secondY)))].!
  749.  
  750. reset
  751.     "Restart the model, with the default values."
  752.  
  753.     view clearInside.
  754.     model initializeLinesAndSteps.
  755.     model setStartLocations.!
  756.  
  757. restart
  758.     "Restart the model, with the default values."
  759.  
  760.     view clearInside.
  761.     model setStartLocations.! !
  762.  
  763. !BouncerController methodsFor: 'model control'!
  764.  
  765. changeModel
  766.     "Modify the model."
  767.  
  768.     model boundingBox == view insetDisplayBox ifFalse: [self updateBoundingBox].
  769.     8 timesRepeat: [model move]!
  770.  
  771. updateBoundingBox
  772.     "The boundingBox has changed, so fix up the model to stay inside."
  773.  
  774.     model boundingBox = Display boundingBox ifTrue: [
  775.         ^self initializeBoundingBox].
  776.     model boundingBox extent <= view insetDisplayBox extent
  777.         ifTrue: [self makeBoundingBoxLarger]
  778.         ifFalse: [self makeBoundingBoxSmaller].
  779.     model boundingBox: view insetDisplayBox! !
  780.  
  781. !BouncerController methodsFor: 'control defaults'!
  782.  
  783. controlActivity
  784.     "Only interested in yellow button activities, apart from
  785.      the changes to the model."
  786.  
  787.     sensor yellowButtonPressed & self viewHasCursor 
  788.         ifTrue: [^self yellowButtonActivity].
  789.     self changeModel.
  790.     super controlActivity!
  791.  
  792. isControlActive
  793.     ^(view containsPoint: sensor cursorPoint) & sensor blueButtonPressed not! !
  794.  
  795. !BouncerController methodsFor: 'private'!
  796.  
  797. initializeBoundingBox
  798.     "First time round, fix the model's boundingBox so that it fits
  799.      within the view's boundingBox."
  800.  
  801.     model boundingBox: self view insetDisplayBox.
  802.     model initializeLinesAndSteps.
  803.     model setStartLocations!
  804.  
  805. makeBoundingBoxLarger
  806.     "Modify the model's positions so that they fix into the new
  807.      display boundingBox."
  808.  
  809.     | offset |
  810.     offset _ model boundingBox origin - view insetDisplayBox origin.
  811.     model positions do: [:eachPair |
  812.         eachPair at: 1 put: (eachPair at: 1) - offset.
  813.         eachPair at: 2 put: (eachPair at: 2) - offset]!
  814.  
  815. makeBoundingBoxSmaller
  816.     "Scale and translate the model's positions so that they fix into the new
  817.      display boundingBox."
  818.  
  819.     | scale mOrigin vOrigin |
  820.     scale _ view insetDisplayBox extent / model boundingBox extent.
  821.     mOrigin _ model boundingBox origin.
  822.     vOrigin _ view insetDisplayBox origin.
  823.     model positions do: [:eachPair |
  824.         eachPair at: 1 put:
  825.             ((eachPair at: 1) - vOrigin * scale) truncated + mOrigin.
  826.         eachPair at: 2 put:
  827.             ((eachPair at: 2) - vOrigin * scale) truncated + mOrigin].! !
  828. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  829.  
  830. BouncerController class
  831.     instanceVariableNames: ''!
  832.  
  833.  
  834. !BouncerController class methodsFor: 'class initialization'!
  835.  
  836. initialize
  837.     "BouncerController initialize."
  838.  
  839.     BouncerYellowButtonMenu _ PopUpMenu
  840.         labels: 'number of lines\x/y steps\restart\reset' withCRs
  841.         lines: #(2).
  842.     BouncerYellowButtonMessages _ #(changeNumberOfLines changeSteps restart reset).! !
  843.  
  844. BouncerController initialize!
  845.  
  846.